package com.bt7274.service.impl;
import com.bt7274.grace.result.GraceJSONResult;
import com.bt7274.mapper.*;
import com.bt7274.pojo.*;
import com.bt7274.utils.SensitiveWordUtil;
import com.bt7274.pojo.bo.PostBO;
import com.bt7274.pojo.bo.PostListBO;
import com.bt7274.pojo.vo.*;
import com.bt7274.service.CommentService;
import com.bt7274.service.EsService;
import com.bt7274.service.PostService;
import com.bt7274.service.UserExpService;
import com.bt7274.utils.SessionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @Data 2025/3/25 02:17
 * @Author hp
 * @Version 1.0
 * @Description UserServiceImpl
 */

@Slf4j
@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private PostMapper postMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CommentService commentService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private ReactionServiceImpl reactionService;
    @Autowired
    private EsService esService;
    @Autowired
    private SensitiveWordUtil sensitiveWordUtil;
    @Autowired
    private UserExpService userExpService;
    @Autowired
    private NotificationMapper notificationMapper;
    @Autowired
    private BtTransactionMapper btTransactionMapper;


    @Override
    public Post selectPostById(String id) {
        return postMapper.selectPostById(id);
    }

    public long countPostList(PostListBO bo) throws IOException {
        // keyword / author 同样逻辑：提前用 ES 过滤 ID
        if ((bo.getKeyword() != null && !bo.getKeyword().isEmpty())
                || (bo.getAuthor() != null && !bo.getAuthor().isEmpty())) {
            List<String> esPostIds = esService.searchPostIdsByKeywordAndAuthor(bo.getKeyword(), bo.getAuthor());
            if (esPostIds == null || esPostIds.isEmpty()) {
                return 0L;
            }
            bo.setPostIds(esPostIds);
        }
        return postMapper.countPostList(bo);
    }
    @Override
    public List<PostListVO> selectPostList(PostListBO bo) throws IOException {
        // 计算分页偏移
        int offset = (bo.getPage() - 1) * bo.getPageSize();
        bo.setOffset(offset);

        // 如果有关键词或作者，则先调用 ES 查询符合条件的帖子 ID
        if ((bo.getKeyword() != null && !bo.getKeyword().isEmpty())
                || (bo.getAuthor() != null && !bo.getAuthor().isEmpty())) {
            System.out.println("啦啦啦");
            List<String> esPostIds = esService.searchPostIdsByKeywordAndAuthor(bo.getKeyword(), bo.getAuthor());
            // 如果没查到，返回空结果
            if (esPostIds == null || esPostIds.isEmpty()) {
                System.out.println("空");
                return List.of(); // 空列表
            }
            bo.setPostIds(esPostIds);
            System.out.println("test"+bo.getPostIds());
            for(String id : esPostIds){
                System.out.println("test"+id);
            }
        }else{
            bo.setFilterPinned(true);
        }
        List<PostListVO> postListVOList = postMapper.selectPostVOList(bo);
        for (PostListVO post : postListVOList) {
            post.setLikeCount(reactionService.getLikeCount(post.getId()));//从redis里读取点赞数
            // 获取发帖人
            User user = userMapper.selectUserById(post.getUserId());
            if (user != null) {
                post.setUserName(user.getUsername());
            }
        }
        return postListVOList;

    }

    public List<PostListVO> getSomeOnePosts(String userId, int page, int pageSize) {
        boolean onlyPublic=true;
        if (userId == null || userId.isEmpty()) {
            userId = SessionUtils.getCurrentUserId();
            onlyPublic=false;
        }

        // 校验用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 计算分页偏移
        int offset = (page - 1) * pageSize;
        // 查询该用户发布的帖子
        List<PostListVO> postList = postMapper.selectSomeOnePosts(userId, offset, pageSize,onlyPublic);

        // 设置每个帖子的用户名
        for (PostListVO post : postList) {
            post.setLikeCount(reactionService.getLikeCount(post.getId()));//从redis里读取点赞数
            post.setUserName(user.getUsername());
        }

        return postList;
    }

    //举报帖子
    public void reportPost(String postId, String reason){
        Post post=postMapper.selectPostById(postId);
        if(post==null){
            throw new RuntimeException("帖子不存在");
        }
        post.setStatus(2);
        //TODO:通知管理员处理
        postMapper.updatePost(post);
    }


    public long countSomeOnePosts(String userId, int page, int pageSize){
        boolean onlyPublic=true;
        if(Objects.equals(userId, "")) {
            userId = SessionUtils.getCurrentUserId();
            onlyPublic=false;
        }
        User user= userMapper.selectById(userId);
        if(user==null)
            throw new RuntimeException("用户不存在");
        return postMapper.countSomeOnePosts(userId,onlyPublic);

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPost(PostBO postBO, String imageUrl) throws IOException {
        Post post = new Post();
        if(imageUrl!=null && !imageUrl.isEmpty()) {
            post.setImageUML(imageUrl);
        }
        BeanUtils.copyProperties(postBO, post);
        String userId = SessionUtils.getCurrentUserId();
        if(userId==null) {
            throw new RuntimeException("用户未登录，无法创建帖子");
        }
        post.setUserId(userId);
        post.setCreatedTime(LocalDateTime.now());
        post.setUpdatedTime(LocalDateTime.now());
        post.setCreatedTime(LocalDateTime.now());
        // 敏感词检测逻辑
        boolean containsSensitive = sensitiveWordUtil.isContaintSensitiveWord(
                post.getTitle() + post.getContent(),2
        );
        if(containsSensitive){
            throw new RuntimeException("帖子中有敏感内容，发布失败");
        }
        post.setStatus(containsSensitive ? 2 : 1); // 2:待审核，1:正常
        postMapper.insertPost(post);
        User user= userMapper.selectUserById(String.valueOf(post.getUserId()));
        try {
            esService.createOrUpdateEsPost(post, user.getUsername());
        } catch (IOException e) {
            // 打印日志（可以换成正式日志记录）
            System.err.println("ES 创建失败，Post ID = " + post.getId());
            e.printStackTrace();
        }

        // 发布帖子奖励5BT币
        boolean rewardSuccess = userExpService.updateBt(userId, 5);
        if (rewardSuccess) {
            log.info("用户{}发布帖子获得5BT币奖励", userId);
            BtTransaction transaction = new BtTransaction();
            transaction.setId(UUID.randomUUID().toString().replace("-", ""));
            transaction.setUserId(userId);
            transaction.setPoints(5);
            transaction.setType("PROMOTION_REWARD");
            transaction.setRuleId("PROMOTION");
            transaction.setDescription("用户发布帖子奖励");
            transaction.setCreatedTime(LocalDateTime.now());
            btTransactionMapper.insert(transaction);
        } else {
            log.warn("用户{}发布帖子奖励BT币失败", userId);
        }
    }

    public void updatePost(PostBO postBO) throws IOException {
        Post post = new Post();
        BeanUtils.copyProperties(postBO, post);
//        String userId=SessionUtils.getCurrentUserId();
//        if(userId==null) {
//            throw new RuntimeException("用户未登录，无法更新帖子");
//        }
//        post.setUserId(userId);
        post.setUpdatedTime(LocalDateTime.now());
        Post origin = postMapper.selectPostById(post.getId());
        if (origin != null) {
            post.setUserId(origin.getUserId());
            // 敏感词检测逻辑
            boolean containsSensitive = sensitiveWordUtil.isContaintSensitiveWord(
                    post.getTitle() + post.getContent(),2
            );
            post.setStatus(containsSensitive ? 2 : 1); // 更新审核状态
            log.info("开始检查是否为精华帖");
            // 检查是否更新为精华帖
            if (post.getType() == 2 && origin.getType() != 2) {
                // 奖励发布者100BT币
                boolean rewardSuccess = userExpService.updateBt(origin.getUserId(), 100);
                if (rewardSuccess) {
                    log.info("用户{}的帖子被设为精华帖，获得100BT币奖励", origin.getUserId());
                    // 发送通知给发布者
                    Notification notification = new Notification();
                    notification.setReceiverId(origin.getUserId());
                    notification.setContent("恭喜！你的帖子《" + post.getTitle() + "》被设为精华帖，获得100BT币奖励！");
                    notification.setSenderId(SessionUtils.getCurrentUserId());
                    notification.setType("post_essence");
                    notification.setCreatedTime(LocalDateTime.now());
                    notificationMapper.insertNotification(notification);
                } else {
                    log.warn("用户{}的帖子被设为精华帖，但奖励BT币失败", origin.getUserId());
                }
            }
            
            origin.setUpdatedTime(LocalDateTime.now());
            BeanUtils.copyProperties(postBO, origin);
            postMapper.updatePost(origin);
            try {
                User user= userMapper.selectUserById(String.valueOf(origin.getUserId()));
                esService.createOrUpdateEsPost(origin, user.getUsername());
            } catch (IOException ignored) {
            }
        } else {
            throw new RuntimeException("帖子不存在，无法更新");
        }
    }

    public PostDetailVO getPostDetail(String postId, int page, int pageSize) {
        page = Math.max(page, 1);
        pageSize = Math.max(pageSize, 1);
        Post post = postMapper.selectPostById(postId);
        if (post == null) {
            throw new RuntimeException("帖子不存在");
        }
        // Redis 中帖子点击量 key
        // 点击量 key
        String viewKey = "post:view:" + postId;
        // Redis 中点击量 +1（用计数器）
        redisTemplate.opsForValue().increment(viewKey);
        // 加入脏帖子集合
        redisTemplate.opsForSet().add("post:dirty_views", postId);
        int totalComments = post.getCommentCount();//TODO:添加评论的时候修改总数
        // 计算总页数
        int totalPages = (int) Math.ceil((double) (totalComments+1) / pageSize);

        // 判断页面是否超出最大页数
        if (page > totalPages) {
            throw new RuntimeException("页码超出范围，最大页码为 " + totalPages);
        }
        post.setLikeCount(reactionService.getLikeCount(postId));
        post.setUnlikeCount(reactionService.getDislikeCount(postId));
        // 构建 PostVO
        PostVO postVO = new PostVO();
        UserVO authorVO = new UserVO();
        if(page==1) {
            BeanUtils.copyProperties(post, postVO);
            System.out.println(post.getUserId()+"test");
            // 获取发帖人
            User user = userMapper.selectUserById(String.valueOf(post.getUserId()));
            if (user != null) {
                BeanUtils.copyProperties(user, authorVO);
                Permission permission=permissionMapper.selectById(user.getPermissionGroup());
                authorVO.setLevel(permission.getName());
            }
        }

        List<CommentVO> commentVOList = commentService.getCommentsByPostId(postId, page, pageSize);

        // 整体封装
        PostDetailVO result = new PostDetailVO();
        result.setPost(postVO);
        result.setAuthor(authorVO);
        result.setComments(commentVOList);
        return result;
    }

    //查询置顶帖列表
    public List<PostListVO> selectPinnedPostList(String forumId){
        List<PostListVO> postListVOList = postMapper.selectPinnedPostList(forumId);
        for (PostListVO post : postListVOList) {
            // 获取发帖人
            User user = userMapper.selectUserById(post.getUserId());
            if (user != null) {
                post.setUserName(user.getUsername());
            }
            post.setLikeCount(reactionService.getLikeCount(post.getId()));//从redis里读取点赞数
        }
        return postListVOList;
    }

    //管理员锁定帖子
    public void lockPost(Post post){
        post.setStatus(3);
        postMapper.updatePost(post);
    }






    @Override
    public int deletePostById(String id) {
        // 先移除缓存
        removePostCache(id);
        // 删除数据库数据
        int rows = postMapper.deletePostById(id);
        try {
            // 删除 ES 索引数据
            esService.deleteEsPost(id);
        } catch (Exception e) {
            // 打印日志（可以换成正式日志记录）
            System.err.println("ES 删除失败，Post ID = " + id);
            e.printStackTrace();
        }
        return rows;
        //TODO:通知被删除用户
    }

    @Override
    public int deletePostByIds(String[] ids) {
        for(String id : ids){
            removePostCache(id);
            try {
                // 删除 ES 索引数据
                esService.deleteEsPost(id);
            } catch (Exception e) {
                // 打印日志（可以换成正式日志记录）
                System.err.println("ES 删除失败，Post ID = " + id);
                e.printStackTrace();
            }
        }
        return postMapper.deletePostByIds(ids);
    }

    public void removePostCache(String postId) {
        redisTemplate.delete("post:like:" + postId);
        redisTemplate.delete("post:dislike:" + postId);
        redisTemplate.delete("post:view:" + postId);
        redisTemplate.opsForSet().remove("reaction:dirty_posts", postId);
    }

}
